﻿using Data.MongoDb.Core;
using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;

namespace Data.MongoDb
{
    public class MongoCollectionWrapper<T, Tid> : Entity.EntityWithTypeId<Tid>
    {
        private readonly IMongoCollection<T> _mongoCollection;


        public MongoCollectionWrapper(IMongoCollection<T> mongoCollection)
        {
            _mongoCollection = mongoCollection;
        }


        public IMongoCollection<T> GetMongoCollection()
        {
            return _mongoCollection;
        }

        public IQueryable<T> AsQueryable()
        {
            return _mongoCollection.AsQueryable<T>();
        }

        public void Insert(T document)
        {
            _mongoCollection.InsertOne(document);
        }

        public void InsertMany(IEnumerable<T> documents)
        {
            _mongoCollection.InsertMany(documents);
        }

        public T FindOneById(Tid Id)
        {
            return _mongoCollection.Find(Builders<T>.Filter.Eq("Id", Id)).First<T>();
        }

        public IEnumerable<T> Find(QueryDocument args)
        {
            return _mongoCollection.Find<T>(args).ToList<T>();
        }

        public DeleteResult Delete(QueryDocument args)
        {
            return _mongoCollection.DeleteMany(args);
        }

        public DeleteResult DeleteById(Tid args)
        {
            return _mongoCollection.DeleteOne(Builders<T>.Filter.Eq("Id", args));
        }

        public UpdateResult Update(FilterDefinition<T> fiter, UpdateDefinition<T> update)
        {
            return _mongoCollection.UpdateMany(fiter, Builders<T>.Update.Combine(update));
        }

        public UpdateResult Update(T args)
        {
            PropertyInfo Id = typeof(T).GetProperty("Id");
            var fiter = Builders<T>.Filter.Eq("Id", Id.GetValue(args));
            IList<UpdateDefinition<T>> update = new List<UpdateDefinition<T>>();
            foreach (PropertyInfo p in args.GetType().GetProperties())
            {
                if (!p.Name.Equals("Id"))
                    update.Add(Builders<T>.Update.Set(p.Name, p.GetValue(args)));
            }
            return _mongoCollection.UpdateOne(fiter, Builders<T>.Update.Combine(update));
        }
    }
}
